package com.quick.proxy.client;

import cn.hutool.json.JSONUtil;
import com.quick.proxy.core.*;
import com.quick.proxy.core.utils.ByteUtils;
import com.quick.proxy.core.utils.LockUtils;
import com.quick.proxy.core.utils.ResponseUtils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Map;


/**
 * Description: 代理消息转发：将代理的消息转发给真实代理客户端
 * Author: 吃素不吃肉
 * Date: 2023/7/3
 *
 * @author 吃素不吃肉
 */
@Match(CmdTypeConstants.FORWARD)
@Component
@Slf4j
public class ProxyMessageForwardHandler implements ProxyMessageHandler {
    /**
     * 接收的数据帧包
     *
     * @param ctx          上下文
     * @param proxyMessage 帧报文
     */
    @Override
    public void cmdResponse(ChannelHandlerContext ctx, ProxyMessage proxyMessage) {
        String data = ByteUtils.hexToString(proxyMessage.getData());
        ForwardMessage forwardMessage = JSONUtil.toBean(data, ForwardMessage.class);
        String visitorId = forwardMessage.getVisitorId();
        byte[] bytes = forwardMessage.getBytes();
        //获取真实代理通道
        Map<String, Channel> visitorIdRealProxyChannel = ctx.channel().attr(ChannelAttribute.VISITOR_ID_REAL_PROXY_CHANNEL).get();
        //需要验证一下是否已经连接成功，如果还未连接成功，需要等待
        if (CollectionUtils.isEmpty(visitorIdRealProxyChannel) || visitorIdRealProxyChannel.get(visitorId) == null) {
            LockUtils.VisitorLock visitorLock = LockUtils.VISITOR_LOCK.get(visitorId);
            visitorLock.await(3000);
            writeAndFlush(ctx, visitorIdRealProxyChannel, visitorId, bytes);
        } else {
            writeAndFlush(ctx, visitorIdRealProxyChannel, visitorId, bytes);
        }
    }

    private void writeAndFlush(ChannelHandlerContext ctx, Map<String, Channel> visitorIdRealProxyChannel, String visitorId, byte[] bytes) {
        if (CollectionUtils.isEmpty(visitorIdRealProxyChannel)) {
            visitorIdRealProxyChannel = ctx.channel().attr(ChannelAttribute.VISITOR_ID_REAL_PROXY_CHANNEL).get();
        }
        if (!CollectionUtils.isEmpty(visitorIdRealProxyChannel)) {
            Channel realProxyChannel = visitorIdRealProxyChannel.get(visitorId);
            if (realProxyChannel != null) {
                realProxyChannel.writeAndFlush(bytes);
                log.debug("visitorId[{}]Receive proxy messages:{}", visitorId, ByteUtils.bytesToHex(bytes));
                return;
            }
        }
        ResponseUtils.disabledConnect(visitorId, ctx.channel());
    }
}
